/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

using System;

using TypeException = argot.TypeException;
using TypeLibrary = argot.TypeLibrary;
using MetaArray = argot.meta.MetaArray;
using MetaDefinition = argot.meta.MetaDefinition;
using MetaEnvelop = argot.meta.MetaEnvelop;
using MetaExpression = argot.meta.MetaExpression;
using MetaMap = argot.meta.MetaMap;
using MetaMarshaller = argot.meta.MetaMarshaller;
using MetaReference = argot.meta.MetaReference;
using MetaSequence = argot.meta.MetaSequence;

namespace argot.dictionary
{
	
	/*
	* A Dictionary file contains a list of specifications for data types.
	* 
	* The MetaDictionary is loaded and used to read the following file dictionary.
	* The file dictionary must then specify all the data types that will be used in 
	* the file.  If meta data types are required these must be replicated in the file
	* dictionary.  This ensures that the data contents do not need to use the types
	* specified by the meta dictionary.  EG A file dictionary might only define an
	* array of a specific type.  The File dictionary is then a small set of words which
	* are defined using the meta dictionary.  The identified data then only contains
	* the data required.
	* 
	* The overall file format does not need to be specified in the file.
	*    sequence( MAGICCODE , dictionary.map, dictionary.map, identified )
	* 
	* A dictionary file format ends up repeating a number of structures.  Especially
	* one that defines the core dictionary.  To write a map to a file, follow this process.
	* 
	* Use a dynamic map(B) as the reference to write a map(A).  The dynamic map(B) will end up
	* containing all the data types required to write the types.  Then use a dynamic map based
	* on typeMapCore(C)
	* to write the created dynamic map(B).  This should resolve to only the data types required
	* to write the data types in the dynamic map(B).  In theory this should be the TypeMapCore
	* with possibly additional data types.  Then write a map with only the extensions(C). Write the 
	* TypeMapCore(D) and put the resulting maps together to form the resulting file.
	* 
	*    MAGICCODE array( 2, (D) (C) ) array( 1, (B) ) identified( (A) )
	* 
	* To write the code, take the TypeMapCore and follow the above process.
	* 
	* MAGICODE
	* MetaDictionary
	* Array(2)
	* 	  Core Meta Dictionary.
	* 		empty, u8, u16...  meta.definitino;
	*    Core Extensions.
	*      envelop
	* FileDictionary
	*    Core File Dictionary
	*      empty, u8, u16...  meta.definition, envelop.
	*      dictionary.file, dictionary.map, dictionary.wordlist, dictionary.triple
	* identified( dictionary.map )
	* UserDictionary
	*    Core User Dictionary
	*      networkvm, etc..
	* 
	* dictionary.file: sequence( dictionary.map, dictionary.map, identified( dictionary.map ) );
	* 
	* dictionary.map: array( u8, ref( dictionary.wordlist ) );
	* 
	* dictionary.wordlist: array( u8, ref( dictionary.triple ) );
	* 
	* dictionary.triple: sequence( u16, meta.name, envelop( u16, meta.definition ) );
	*/
	public class DictionaryMap
	{
		
		public static void  LoadDictionaryMap(TypeLibrary library)
		{
			MetaEnvelop me = new MetaEnvelop(null, null);
			MetaDefinition meDef = new MetaSequence(
				new MetaExpression[]{
					new MetaReference(library.GetId("meta.expression"), "size"), 
					new MetaReference(library.GetId("meta.expression"), "type")
				}
			);			
			library.Register("meta.envelop", meDef, me, me, me.GetType());

			
			MetaMap exprRefDef = new MetaMap(library.GetId("meta.definition"), library.GetId("meta.envelop"));
			library.Register("meta.definition#envelop", exprRefDef, new MetaMarshaller(), new MetaMarshaller(), null);
			
			MetaDefinition dDef = new MetaEnvelop(
				new MetaReference(library.GetId("u16"), "size"), 
				new MetaReference(library.GetId("meta.definition"), "definition")
			);
			library.Register("dictionary.definition", dDef, new MetaMarshaller(), new MetaMarshaller(), null);
			
			MetaDefinition tDef = new MetaSequence(
				new MetaExpression[]
				{
					new MetaReference(library.GetId("u16"), "id"), 
					new MetaReference(library.GetId("meta.name"), "name"), 
					new MetaReference(library.GetId("dictionary.definition"), "definition")
				}
			);
			library.Register("dictionary.entry", tDef, new MetaMarshaller(), new MetaMarshaller(), null);
			
			TypeMapMarshaller tmm = new TypeMapMarshaller();
			MetaDefinition dmDef = new MetaSequence(
				new MetaExpression[]
				{
					new MetaArray(
						new MetaReference(library.GetId("u16"), "size"), 
						new MetaReference(library.GetId("dictionary.entry"), "word")
					)
				}
			);
			library.Register("dictionary.map", dmDef, tmm, tmm, null);
			
			MetaDefinition dWords = new MetaEnvelop(
				new MetaReference(library.GetId("u16"), "size"), 
				new MetaReference(library.GetId("dictionary.map"), "words")
			);
			library.Register("dictionary.words", dWords, new MetaMarshaller(), new MetaMarshaller(), null);
		}
	}
}